package com.octo.musicstore.controller;

import java.util.StringTokenizer;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.musicstore.model.Album;
import com.musicstore.model.Albums;
import com.octo.musicstore.errorHandler.EntityAlreadyExistingException;
import com.octo.musicstore.errorHandler.IncompleteInformationException;
import com.octo.musicstore.errorHandler.InvalidParamException;
import com.octo.musicstore.errorHandler.RessourceNotFoundException;
import com.octo.musicstore.errorHandler.UpdateErrorException;


@Controller
@RequestMapping("/albums")
public class AlbumController {
	Albums albums;//model

	public AlbumController(){
		albums = new Albums();
	}

	//list one album

	//list albums
	@RequestMapping(method = RequestMethod.GET)
	public @ResponseBody Albums getAlbums() {
		return albums;
	}

	//check whether the album is in the list or not
	//search a album for the price
	//peut-etre il y a aucun de sens pour cette methode
	//alors, c'est juste pour verifier le facon d'utiliser plusieurs parametter pour le GET
	//je crois que l'on ne peut pas utiliser le requestbody
	//mais je ne suis pas sur
	@RequestMapping(value="/search/{albumTitre}/{albumArtist}/{albumStyle}", method = RequestMethod.GET)
	public @ResponseBody Albums getAlbum(@PathVariable String albumTitre, 
			@PathVariable String albumArtist,
			@PathVariable String albumStyle) {

		String titre = null;
		String artist = null;
		String style = null;


		//parce que lorsque on utilise le "MultiValueMap" pour transmettre plusieurs parameters
		//alors, ici on va avoir les parameter en format:"[value]"
		//cette partie au dessus, c'est pour recuperer le valeur reel dans le [];
		StringTokenizer st = new StringTokenizer(albumTitre, "[]"); 
		if(st.hasMoreTokens()) { 
			titre = st.nextToken(); 
		} 
		st = new StringTokenizer(albumArtist, "[]"); 
		if(st.hasMoreTokens()) { 
			artist = st.nextToken(); 
		} 
		st = new StringTokenizer(albumStyle, "[]"); 
		if(st.hasMoreTokens()) { 
			style = st.nextToken(); 
		} 

		System.out.println("titre:"+albumTitre);
		System.out.println("artist:"+albumArtist);
		System.out.println("style:"+albumStyle);

		Albums ret = new Albums();
		byte conditions = (byte)0;
		if(titre!=null){
			conditions = (byte) (conditions + (byte)(1));
		}
		if(artist!=null){
			conditions = (byte) (conditions + (byte)(2));
		}
		if(style!=null){
			conditions = (byte) (conditions + (byte)(4));
		}		
		System.out.println("conditions:"+conditions);
		switch(conditions){
		case (byte)0:
			break;		
		case (byte)1:
			ret = albums.searchByTitre(titre);
		break;
		case (byte)2:
			ret = albums.searchByArtiste(artist);
		break;
		case (byte)3:
			ret = albums.searchByTitre(titre).searchByArtiste(artist);
		break;
		case (byte)4:
			ret = albums.searchByStyle(style);
		break;
		case (byte)5:
			ret = albums.searchByTitre(titre).searchByStyle(style);
		break;
		case (byte)6:
			ret = albums.searchByArtiste(artist)
			.searchByStyle(style);
		break;
		case (byte)7:
			ret = albums.searchByTitre(titre)
			.searchByArtiste(artist)
			.searchByStyle(style);
		break;
		default:
			break;
		}
		return ret;	
	}


	/**
	 * =======================GET:Search =============================
	 */

	//list albums by ID
	@RequestMapping(value="/search/id/{albumid}", method = RequestMethod.GET)
	public @ResponseBody Album getalbumsById(@PathVariable int albumid) {
		if (albumid < 0) {  
			throw new InvalidParamException(); 
		} 
		Album foundedAlbum = albums.searchById(albumid);
		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}

		return foundedAlbum;


	}

	//list albums by titre 
	@RequestMapping(value="/search/titre/{albumTitre}", method = RequestMethod.GET)
	public @ResponseBody Albums getalbumsByTitre(@PathVariable String albumTitre) {
		if(albumTitre == null) throw new InvalidParamException();
		Albums foundedAlbum = albums.searchByTitre(albumTitre);
		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}		
		return foundedAlbum;		
	}

	//list albums by artist
	@RequestMapping(value="/search/artist/{albumArtist}", method = RequestMethod.GET)
	public @ResponseBody Albums getalbumsByArtist(@PathVariable String albumArtist) {
		if(albumArtist == null || albumArtist.trim() == "") throw new InvalidParamException();
		Albums foundedAlbum = albums.searchByArtiste(albumArtist);
		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}		
		return foundedAlbum;
	}

	//list albums by style
	@RequestMapping(value="/search/style/{albumStyle}", method = RequestMethod.GET)
	public @ResponseBody Albums getalbumsByStyle(@PathVariable String albumStyle) {
		if(albumStyle == null || albumStyle.trim() == "") throw new InvalidParamException();
		Albums foundedAlbum = albums.searchByStyle(albumStyle);
		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}		
		return foundedAlbum;
	}	

	//search by the criteria of price
	@RequestMapping(value="/search/price/{bottom}/{top}", method = RequestMethod.GET)
	@ResponseStatus(HttpStatus.OK)
	public @ResponseBody Albums getalbumsByPrice(@PathVariable String bottom, @PathVariable String top){		
		System.out.println("Getting albums by price: "+bottom);
		
		float l_bottom;
		float l_top;
		try{
			l_bottom = Float.valueOf(bottom);
			l_top = Float.valueOf(top);
		}catch(Exception e){
			throw new InvalidParamException();
		}

		if(l_bottom < 0 || l_top < 0) throw new InvalidParamException();

		Albums foundedAlbum = new Albums();
		try{
			foundedAlbum = albums.searchByPrices(l_bottom, l_top);
			System.out.println("empty: "+foundedAlbum.isEmpty());
			if(foundedAlbum==null || foundedAlbum.isEmpty()){
				throw new RessourceNotFoundException();
			}
		}catch(Exception e){};

		return foundedAlbum;
	}	

	//search by the criteria of price
	@RequestMapping(value="/calculateReduction/{style}/{reductionPercent}", method = RequestMethod.GET)
	@ResponseStatus(HttpStatus.OK)
	public @ResponseBody Albums calculateReduction(@PathVariable String style, @PathVariable String reductionPercent){		
		System.out.println("Calculating promotion albums: "+ style);

		float reduction = 0;
		try{
			reduction = Float.valueOf(reductionPercent);
		}catch(Exception e){
			throw new InvalidParamException();
		}

		if(reduction < 0 || reduction > 100 || style.trim() == "" || style == null){
			throw new InvalidParamException();
		}

		Albums foundedAlbum = new Albums();
		Albums promotionAlbmus = new Albums();
		try{
			foundedAlbum = albums.searchByStyle(style);
			if(foundedAlbum==null || foundedAlbum.isEmpty()){
				throw new RessourceNotFoundException();
			}

			promotionAlbmus = foundedAlbum.getReduction(reduction);

		}catch(Exception e){};


		return promotionAlbmus;
	}	



	/**
	 * =======================POST: Add =============================
	 */

	//add a album to a album-list
	@RequestMapping(value = { "/add" }, method = RequestMethod.POST)
	@ResponseStatus( HttpStatus.CREATED )
	@ResponseBody
	public boolean addAlbum(@RequestBody Album album){
		boolean result = false;
		if(album.getTitre() == null || album.getArtiste() == null ||album.getStyle() == null ) {	
			throw new IncompleteInformationException();
		}

		if(album.getPrix() < 0) throw new InvalidParamException();
		if(album.getReduction() < 0 || album.getReduction() > 1)  throw new InvalidParamException();

		else{
			result = albums.addAlbum(album); 
			if(!result) throw new EntityAlreadyExistingException();
			//if(album == null) throw new InvalidParamException();	
			return result;
		}
	}	



	/**
	 * ========================PUT: modifier=============================
	 */
	@RequestMapping(value= "/modifyAlbumById/{albumid}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	public void modifyAlbumById(@RequestBody Album alb, @PathVariable("albumid") int albumid) {
		System.out.println("Updating Album: " + albumid); 

		if (albumid < 0) {  
			throw new InvalidParamException(); 
		} 

		Album foundedAlbum = null;
		foundedAlbum = albums.searchById(albumid);

		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}else{		
			try{
				foundedAlbum.update(alb);
			}catch(Exception e){
				throw new UpdateErrorException();
			}			
		}
	}

	@RequestMapping(value= "/modifyTitre/{albumid}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	public void modifyTitre(@RequestBody String newTitre, @PathVariable("albumid") int id) {
		System.out.println("Updating titre by id: " + id); 

		if ( id < 0 || newTitre.isEmpty()) {  
			throw new InvalidParamException(); 
		} 

		Album foundedAlbum = null;
		foundedAlbum = albums.searchById(id);

		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}else{		
			try{
				foundedAlbum.setTitre(newTitre);
			}catch(Exception e){
				throw new UpdateErrorException();
			}			
		}
	}

	/*
	@RequestMapping(value= "/modifyStyle/{albumid}/{newstyle}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	@ResponseBody
	public boolean modifyStyle(@PathVariable("albumid") int albumid, @PathVariable("newStyle") String newStyle) {
		return albums.modifyStyle(albumid,newStyle);
	}

	@RequestMapping(value= "/modifyStyle/{albumid}/{newartist}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	@ResponseBody
	public boolean modifyArtist(@PathVariable("albumid") int albumid, @PathVariable("newArtist") String newArtist) {
		return albums.modifyArtiste(albumid,newArtist);
	}

	 */
	@RequestMapping(value= "/modifyPrix/{albumid}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	public void modifyPrix(@RequestBody float newPrix, @PathVariable("albumid") int id) {
		System.out.println("Updating prix by id: " + id); 

		if ( id < 0 || newPrix < 0) {  
			throw new InvalidParamException(); 
		} 

		Album foundedAlbum = null;
		foundedAlbum = albums.searchById(id);

		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}else{		
			try{
				foundedAlbum.setPrix(newPrix);
			}catch(Exception e){
				throw new UpdateErrorException();
			}			
		}
	}

	/*
	@RequestMapping(value= "/modifyReduction/{albumid}/{newreduction}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	@ResponseBody
	public boolean modifyReduction(@PathVariable("albumid") int albumid, @PathVariable("newprix") float newReduction) {
		return albums.modifyReduction(albumid,newReduction);
	}

	@RequestMapping(value= "/modifyAlbumbyPriceInterval/{bottom}/{top}",method = RequestMethod.PUT)
	@ResponseStatus( HttpStatus.OK)
	@ResponseBody	
	public boolean modifyReduction(@RequestBody float reduction, @PathVariable("bottom") float bottom,@PathVariable("top") float top) {
		boolean flag = true;
		//float reduction = alb.getReduction();
		Albums ret = albums.searchByPrices(bottom,top);
		if(ret.isEmpty()){
			return false;
		}
		for(Album l_alb : ret){
			if(!ret.modifyReduction(l_alb.getId(), reduction)){
				flag = false;
			}
		}
		return flag;
	}
	 */
	/**
	 * =======================DELETE: supprimer=============================
	 */	

	@RequestMapping(value= "/deletebyTitle/{titre}",method = RequestMethod.DELETE)
	@ResponseStatus( HttpStatus.OK)
	public void delAlbumbyTitre(@PathVariable String titre) {			
		System.out.println("Deleting album by titre: " + titre); 

		String formatedTitle = titre.trim();

		if (formatedTitle.equals("")) {  
			throw new InvalidParamException(); 
		} 

		Albums foundedAlbum = null;
		foundedAlbum = albums.searchByTitre(formatedTitle);

		if(foundedAlbum == null || foundedAlbum.size() == 0){
			throw new RessourceNotFoundException();
		}else{		
			try{
				albums.removeAll(foundedAlbum);
			}catch(Exception e){
				throw new UpdateErrorException();
			}			
		}	
	}

	/*
	@RequestMapping(value= "/deletebyArtist/{artist}",method = RequestMethod.DELETE)
	@ResponseStatus( HttpStatus.OK)
	@ResponseBody
	public boolean delAlbumbyArtist(@PathVariable String artist) {
		boolean flag = albums.removeByArtist(artist);
		if(flag){
			albums.sortId();
		}
		return flag;	

	}

	@RequestMapping(value= "/deletebyStyle/{style}",method = RequestMethod.DELETE)
	@ResponseStatus( HttpStatus.OK)
	@ResponseBody
	public boolean delAlbumbyStyle(@PathVariable String style) {
		boolean flag = albums.removeByStyle(style);
		if(flag){
			albums.sortId();
		}
		return flag;	
	}*/

	@RequestMapping(value= "/deletebyId/{id}",method = RequestMethod.DELETE)
	@ResponseStatus( HttpStatus.OK)
	public void delAlbumbyStyle(@PathVariable int id) {
		System.out.println("Deleting album by id: " + id); 

		if ( id < 0) {  
			throw new InvalidParamException(); 
		} 

		Album foundedAlbum = null;
		foundedAlbum = albums.searchById(id);

		if(foundedAlbum == null){
			throw new RessourceNotFoundException();
		}else{		
			try{
				albums.removeById(id);
			}catch(Exception e){
				throw new UpdateErrorException();
			}			
		}	
	}	

	@RequestMapping(value= "/deleteAll",method = RequestMethod.DELETE)
	@ResponseStatus( HttpStatus.OK)
	public void delAll() {
		System.out.println("Deleting all album"); 

		try{
			albums.clear();
		}catch(Exception e){				
		}	
	}
}
